package com.cl.security.core.service;

import cn.hutool.core.bean.BeanUtil;
import com.cl.security.base.service.BaseService;
import com.cl.security.common.result.CommonResult;
import com.cl.security.core.entity.Product;
import com.cl.security.core.entity.Property;
import com.cl.security.core.entity.PropertyValue;
import com.cl.security.core.entity.Sku;
import com.cl.security.core.repository.ProductRepository;
import com.cl.security.core.repository.PropertyValueRepository;
import com.cl.security.core.repository.SkuRepository;
import com.cl.security.system.entity.FileInfo;
import com.cl.security.system.service.FileInfoService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class ProductService extends BaseService<Product, ProductRepository> {
    private final SkuRepository skuRepository;
    private final PropertyValueRepository propertyValueRepository;
    private final ProductRepository productRepository;
    private final FileInfoService fileInfoService;
    protected ProductService(ProductRepository repository, SkuRepository skuRepository, PropertyValueRepository propertyValueRepository, FileInfoService fileInfoService) {
        super(repository);
        this.skuRepository = skuRepository ;
        this.productRepository = repository;
        this.propertyValueRepository = propertyValueRepository;
        this.fileInfoService = fileInfoService;
    }

    @Transactional
    public CommonResult uploadPropertyValueImage(MultipartFile file,Long id) {
        FileInfo image = fileInfoService.upload(file).getData();
        if (image != null) {
            PropertyValue propertyValue = propertyValueRepository.findById(id).get();
            propertyValue.setImage(image);
            propertyValueRepository.save(propertyValue);
            return CommonResult.success(image);
        }
        return CommonResult.failed("上传失败");
    }

    @Transactional
    public CommonResult generateSku(Long productId) {
        Product product = productRepository.findById(productId).get();
        Set<Property> properties = product.getCategory().getProperties();
        Set<PropertyValue> propertyValues = product.getPropertyValues();
        Set<Sku> skus = new HashSet<>();
        List<Set<PropertyValue>> propertyValuesList = new ArrayList<>();
        properties.forEach(property -> {
            Set<PropertyValue> tempPVSet = new HashSet<>();
            propertyValues.forEach(propertyValue -> {
                if (property.getId().equals(propertyValue.getPropertyId())) {
                    tempPVSet.add(propertyValue);
                }
            });
            propertyValuesList.add(tempPVSet);
        });
        Sku sku = new Sku();
        sku.setProduct(product);
        generateSkuPropertyValues(sku,0,propertyValuesList,skus);
        product.getSkus().clear();
        productRepository.save(product);
        skuRepository.saveAll(skus);
        skus.forEach(sku1 -> {
            sku1.setPropertyValues(sku1.getPropertyValues().stream().sorted(Comparator.comparing(PropertyValue::getPropertyId)).collect(Collectors.toCollection(LinkedHashSet::new)));
        });

        return CommonResult.success(skus);
    }

    /**
     * 回溯遍历商品的属性值生成sku
     * @param sku
     * @param index
     * @param propertyValuesList
     * @param skus
     */
    private void generateSkuPropertyValues(Sku sku,int index,List<Set<PropertyValue>> propertyValuesList,Set<Sku> skus) {
        if (index==propertyValuesList.size()) {
            Sku newSku = new Sku();
            BeanUtil.copyProperties(sku,newSku);
            newSku.setPropertyValues(new HashSet<>(sku.getPropertyValues()));
            skus.add(newSku);
            return;
        }
        int[] indexs = {index};
        Set<PropertyValue> propertyValues = propertyValuesList.get(index);
        propertyValues.forEach(propertyValue -> {
            sku.getPropertyValues().add(propertyValue);
            generateSkuPropertyValues(sku,++indexs[0],propertyValuesList,skus);
            sku.getPropertyValues().remove(propertyValue);
            --indexs[0];
        });
    }
}
